package com.dongdongshop.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONObject;
import com.dongdongshop.mapper.TbSeckillGoodsMapper;
import com.dongdongshop.pojo.TbSeckillGoods;
import com.dongdongshop.pojo.TbSeckillGoodsExample;
import com.dongdongshop.pojo.TbSeckillOrder;
import com.dongdongshop.service.SeckillGoodsService;
import com.dongdongshop.service.SeckillOrderService;
import com.dongdongshop.util.IdWorker;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * @Description
 * @ClassName SeckillGoodsServiceImpl
 * @Author RC
 * @date 2020.12.30 16:22
 */
@Component
@Service
public class SeckillGoodsServiceImpl implements SeckillGoodsService {
    @Autowired
    private TbSeckillGoodsMapper tbSeckillGoodsMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Reference(timeout = 100000,check = false)
    private SeckillOrderService seckillOrderService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @Override
    public List<TbSeckillGoods> showSeckillList() {

        //先判断缓存中是否有数据
        List<TbSeckillGoods> seckillGoods = redisTemplate.boundHashOps("seckillGoods").values();
      /* if(seckillGoods ==null || seckillGoods.size() <=0){
            //没有 条件查询数据库放入缓存
            TbSeckillGoodsExample example = new TbSeckillGoodsExample();
            TbSeckillGoodsExample.Criteria criteria = example.createCriteria();
            criteria.andStatusEqualTo("1");//已审核
            criteria.andStockCountGreaterThan(0);//库存大于0
            Date now = new Date();
            criteria.andStartTimeLessThan(now);//开始时间 <= now
            criteria.andEndTimeGreaterThan(now);//结束时间 >= now 
            seckillGoods = tbSeckillGoodsMapper.selectByExample(example);
            //遍历 放入缓存
            redisTemplate.setValueSerializer(new StringRedisSerializer());//序列化原因 1 是一旦使用原子性的自增操作  value使用这种方式序列化
            for (TbSeckillGoods seckillGood : seckillGoods) {
                redisTemplate.boundHashOps("seckillGoods").put(seckillGood.getId(),seckillGood);
                //查询时候需要将预减库存 放入redis中
                redisTemplate.boundValueOps("stockCount_"+ seckillGood.getId()).set(seckillGood.getStockCount().toString());// 存储 也是字符串存储
            }
        }*/
        //有直接返回
        return seckillGoods;
    }

    @Override
    public TbSeckillGoods getSeckillGoodsById(Long id) {
        return (TbSeckillGoods)redisTemplate.boundHashOps("seckillGoods").get(id);
    }

    @Override
    public void sumitOrder(Long seckillId, String username) {
        //redis序列化
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        //先从redis中取出预减库存
        Integer stockCount =Integer.parseInt(redisTemplate.boundValueOps("stockCount_" + seckillId).get()+"") ;
        TbSeckillGoods seckillGoods =(TbSeckillGoods) redisTemplate.boundHashOps("seckillGoods").get(seckillId);
        if(seckillGoods == null || stockCount <= 0){
            //void 无返回值 使用异常来代替返回值
            throw new RuntimeException("商品被抢光了");
        }

        // 如果有 就进行减库存 并且生成订单
        //seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
        //更新缓存
       // redisTemplate.boundHashOps("seckillGoods").put(seckillId,seckillGoods);

        Long decrement = redisTemplate.boundValueOps("stockCount_" + seckillId).decrement();
        // 如果有 就进行减库存 并且生成订单
        seckillGoods.setStockCount(decrement.intValue());
        //更新缓存
         redisTemplate.boundHashOps("seckillGoods").put(seckillId,seckillGoods);
        //如果减库完成之后刚好是最后一件商品需要更新数据库 并且清除缓存 if(seckillGoods.getStockCount())
        if(decrement == 0){
            //seckillGoods.setStockCount(0);
            tbSeckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
            //清除缓存
            redisTemplate.boundHashOps("seckillGoods").delete(seckillId);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("seckillId",seckillId);
        jsonObject.put("username",username);
        String jsonString = jsonObject.toJSONString();
        rocketMQTemplate.convertAndSend("seckill",jsonString);
        // 不是最后一件商品  就下单
        /*TbSeckillOrder seckillOrder = new TbSeckillOrder();
        IdWorker idWorker = new IdWorker();
        seckillOrder.setId(idWorker.nextId());
        seckillOrder.setCreateTime(new Date());
        seckillOrder.setMoney(seckillGoods.getCostPrice());
        seckillOrder.setSeckillId(seckillId);
        seckillOrder.setSellerId(seckillGoods.getSellerId());
        seckillOrder.setStatus("0");
        seckillOrder.setUserId(username);
        //保存订单
        seckillOrderService.createOrder(seckillOrder);*/

    }

    @Override
    public TbSeckillOrder findOrderByUsername(String username) {
        return (TbSeckillOrder)redisTemplate.boundHashOps("seckillOrder").get(username);
    }
}
